#pragma once

#include "noncopyable.h"
#include"Timestamp.h"

#include <functional>
#include<memory>


//只使用到了类型的名称，比如指针，引用等只需要前置声明类型，不需要包括头文件，
//如果需要知道变量的大小以及内部成员的具体定义时，必须包含头文件
//比如下面的EventLoop只使用了指针，前置声明即可，Timestamp需要知道大小，需要包含头文件
//在源文件中使用的，在cc文件中包括就可以了，到时候cc文件编译成动态库，不会暴露出太多内容
class EventLoop;
//class Timestamp;


// Channel 理解为通道，封装了sockfd和感兴趣的event，如EPOLLIN
//one loop per thread
//一个线程一个eventLoop，一个loop有一个poller，一个poller监听很多channel
// 绑定具体事件
class Channel : noncopyable
{
public:
    using EventCallback = std::function<void()>;
    using ReadEventCallback = std::function<void(Timestamp)>;


    Channel(EventLoop* loop, int fd);
    ~Channel();

    //fd可读可写后，回调事件
    void headleEvent(Timestamp receiveTime);

    void setReadCallback(ReadEventCallback cb) {readCallback_ = std::move(cb);}
    void setWriteCallback(EventCallback cb) {writeCallback_ = std::move(cb);}
    void setErrorCallback(EventCallback cb) {errorCallback_ = std::move(cb);}
    void setCloseCallback(EventCallback cb) {closeCallback_ = std::move(cb);}

    //防止当channel被手动remove时，channel还在执行回调
    
    void tie(const std::shared_ptr<void>&);

    int fd() const {return fd_;}
    int events() const {return events_;}
    void set_revents(int revt) {revents_ = revt;}
    //bool isNoneEvent() const {return events_ == KNoneEvent;}

    //设置fd对应的事件，epoll_ctl
    void enableReading(){events_ |= KReadEvent;update(); }
    void enableWriting(){events_ |= KWriteEvent;update(); }
    void disableReading(){events_ &= ~KReadEvent;update(); }
    void disableWriting(){events_ &= ~KWriteEvent;update(); }
    void disableALL(){events_ = KNoneEvent;update();}

    //返回fd当前的事件状态
    bool isNoneEvent() const{return events_ == KNoneEvent;}
    bool isReading() const {return events_ & KReadEvent;}
    bool isWriting() const {return events_ & KWriteEvent;}

    int index() {return index_;}
    void set_index(int idx) {index_ = idx;}

    EventLoop* ownerLoop() {return loop_;}
    void remove();

private:

    void update();
    void handleEventWithGuard(Timestamp receiveTime);

    //fd的状态信息，对某件事感兴趣
    static const int KNoneEvent;
    static const int KReadEvent;
    static const int KWriteEvent;

    EventLoop *loop_;//事件循环
    const int fd_;  //poller监听的对象，一个线程一个EventLoop, 一个EventLoop一个poller，一个poller监听多个fd
    int events_; //注册fd感兴趣的事件
    int revents_;//poller返回的具体发生的事情
    int index_;

    //用于判断对象是否还存在
    std::weak_ptr<void> tie_;
    bool tied_;
    //因为channel知道fd最终发生的事件revent，因此它负责具体的回调操作
    ReadEventCallback readCallback_;
    EventCallback writeCallback_;
    EventCallback closeCallback_;
    EventCallback errorCallback_;
};